Skip to content

Add groups#196

Merged
harshal-2304 merged 4 commits into
devfrom
add-groups
May 30, 2026
Merged

Add groups#196
harshal-2304 merged 4 commits into
devfrom
add-groups

Conversation

@tenkus47

Copy link
Copy Markdown
Member

No description provided.

tenkus47 added 3 commits May 28, 2026 23:23
- Updated package version to 2026.05.28.1200.
- Introduced new routes for managing groups, including group creation, editing, and details pages.
- Enhanced the Navbar to include a link for groups management.
- Modified PlanTagSearchInput to conditionally hide the label.
- Replaced error handling in Tags component to utilize a centralized API error message function.
- Added PlanAudioDTO and PlanAudioListResponse interfaces for audio data handling.
- Implemented fetchPlanAudioList function to retrieve audio files associated with plans.
- Introduced attachDayAudio function to link audio files to specific days.
- Updated TaskForm to include plan title in DayAudioSection.
- Integrated PlanAudioSearchInput component for searching existing audio files in DayAudioSection.
- Improved user instructions for audio uploads and management in the UI.
…sk management

- Added new API functions for creating multiple days and bulk deleting days.
- Updated the SideBar component to support day selection mode for bulk actions.
- Enhanced the DayDeleteDialog to handle bulk deletion.
- Refactored usePlanMutations to integrate new API functions for creating and deleting days.
- Improved user experience with feedback messages for successful and failed operations.
@greptile-apps

greptile-apps Bot commented May 29, 2026

Copy link
Copy Markdown

Confidence Score: 3/5

The bulk-delete path in the sidebar has a real regression that can wipe all days from a plan.

The bulk day-delete handler does not enforce a minimum number of surviving days. A user with a two-day plan can enter select mode, choose both days, confirm, and delete the entire plan's day list — behavior the old guard was specifically designed to prevent. This is a functional regression on the plan editing path.

src/components/routes/task/components/sidebar-component/SideBar.tsx — the bulk delete confirmation and the delete button disable logic need a guard to keep at least one day.

Reviews (2): Last reviewed commit: "feat(plan-audio): place plan filter besi..." | Re-trigger Greptile

Comment thread src/lib/constant.ts
Comment on lines 20 to 23
export const SOCIAL_PLATFORMS = [
{ value: "facebook", label: "Facebook", icon: "Facebook" },
{ value: "SignIn", label: "SignIn", icon: "SignIn" },
{ value: "x.com", label: "X (Twitter)", icon: "Twitter" },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Erroneous "SignIn" social platform entry

"SignIn" is not a social platform and appears to be an accidental addition. It will show up in the platform dropdown in GroupSocialLinksEditor as a real option for every group's social links, producing malformed data.

Suggested change
export const SOCIAL_PLATFORMS = [
{ value: "facebook", label: "Facebook", icon: "Facebook" },
{ value: "SignIn", label: "SignIn", icon: "SignIn" },
{ value: "x.com", label: "X (Twitter)", icon: "Twitter" },
export const SOCIAL_PLATFORMS = [
{ value: "facebook", label: "Facebook", icon: "Facebook" },
{ value: "x.com", label: "X (Twitter)", icon: "Twitter"},

Comment on lines +357 to +394
render={({ field }) => (
<Pecha.FormItem className="flex items-center gap-3">
<Pecha.FormControl>
<Pecha.Checkbox
checked={field.value}
onCheckedChange={(checked) =>
field.onChange(checked === true)
}
/>
</Pecha.FormControl>
<Pecha.FormLabel className="text-sm font-bold !mt-0">
Public group
</Pecha.FormLabel>
</Pecha.FormItem>
)}
/>
<div className="space-y-4">
{addedLanguages.map((code) => (
<div
key={code}
className="relative rounded-lg border border-input bg-[#FAFAFA] dark:bg-[#262626] p-4 space-y-3"
>
<button
type="button"
onClick={() => removeLanguage(code)}
className="absolute top-2 right-2 text-muted-foreground hover:text-foreground p-1"
aria-label={`Remove ${languageLabelForCode(code)}`}
>
<IoMdClose className="h-4 w-4" />
</button>
<Pecha.FormField
control={form.control}
name={`languages.${code}.title`}
render={({ field }) => (
<Pecha.FormItem>
<Pecha.FormLabel className="text-sm font-bold">
{languageLabelForCode(code)} title
</Pecha.FormLabel>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Plan titles show as IDs due to hydration race condition

The hydration effect guards on hydratedRef.current === groupData.id to avoid running twice, but planOptions is an async query that may arrive after groupData. When that happens, the effect runs with planOptions = [], sets hydratedRef, and when planOptions finally populates (triggering the effect again), the hydratedRef guard returns early — leaving selectedPlans filled with raw IDs as titles via the titleById.get(id) ?? id fallback.

The series_ids hydration correctly avoids this by using a separate useEffect that fetches titles independently; the plan_ids side needs the same treatment.

Comment thread src/components/routes/groups/GroupFormPage.tsx

setUploading(true);
try {
const { image, key } = await uploadImageToS3(file, groupId ?? "");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Image upload passes empty string as groupId for new groups

When isNew is true, groupId is undefined, so uploadImageToS3(file, groupId ?? "") sends "" to the upload API. If the server uses this parameter for path/ownership resolution, the upload may be rejected or filed under an unowned S3 prefix. The image upload dialogs are rendered unconditionally so a user can trigger this code path before creating the group.

Suggested change
const { image, key } = await uploadImageToS3(file, groupId ?? "");
if (!groupId) {
toast.error("Save the group first before uploading images");
return;
}
const { image, key } = await uploadImageToS3(file, groupId);

- lay out plan picker and audio library search on one row in day audio UI
- preserve search, infinite scroll, preview, and attach behavior
- apply formatting-only updates across groups routes and day create dialog
Comment on lines +76 to +90
};

const toggleDaySelection = (day_id: string) => {
setSelectedDayIds((prev) => {
const next = new Set(prev);
if (next.has(day_id)) {
next.delete(day_id);
} else {
next.add(day_id);
}
return next;
});
};

const exitSelectMode = () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Bulk delete can remove all days from a plan

The single-day delete path was guarded by isEditable && currentPlan?.days.length > 1, ensuring at least one day always remains. The new bulk delete path only requires displayDays.length > 1 to enter select mode, but once inside, all days can be selected and deleted together. A plan with 2 days allows entering select mode, selecting both, and wiping out every day — leaving the plan in a zero-day state that may be invalid server-side or unrecoverable through the UI.

@tenkus47 tenkus47 requested a review from Tech-lo May 30, 2026 13:23
@harshal-2304 harshal-2304 merged commit ce633ff into dev May 30, 2026
3 checks passed
@harshal-2304 harshal-2304 deleted the add-groups branch May 30, 2026 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants